layui.define(['jquery'], function (exports) {
    var MOD_NAME = 'treeTable', j = layui.jquery, tree = function () {
    };
    tree.prototype.config = function () {
        return {
            top_value: 0,
            primary_key: 'id',
            parent_key: 'pid',
            hide_class: 'layui-hide',
            icon: {
                open: 'layui-icon layui-icon-triangle-d',
                close: 'layui-icon layui-icon-triangle-r',
                left: 16,
            },
            where: {},
            cols: [],
            checked: {},
            is_checkbox: false,
            is_cache: true,
            code: 0,
            toolbar: false,
            error: false,
            render: {toolbar: true, thead: true, tbody: true}
        };
    }
    // 存储折叠状态
    tree.prototype.cache = function (e, val, option) {
        if (!e.is_cache) {
            return false;
        }
        var name = e.elem.substring(1),
            val = val.toString(),
            cache = localStorage.getItem(name) ? localStorage.getItem(name).split(',') : [],
            index = j.inArray(val, cache);
        if (option === undefined) {
            return index == -1 ? false : val
        }
        if (option && index == -1) {
            cache.push(val)
        }
        if (!option && index > -1) {
            cache.splice(index, 1)
        }
        localStorage.setItem(name, cache.join(','));
    };
    tree.prototype.renderTableTool = function (e) {
        var dom = '', n = j(e.elem).next();
        if (e.render.toolbar && n.children('.layui-table-tool').remove()) {
            if (e.toolbar && e.toolbar.constructor === String && e.toolbar.slice(0, 1) === '#') {
                dom = '<div class="layui-table-tool"><div class="layui-table-tool-temp">' + j(e.toolbar).html() + '</div></div>';
            }
            n.prepend(dom);
        }
    };
    tree.prototype.renderCkBox = function (checked) {
        var checkbox = '<div class="layui-unselect layui-form-checkbox cbx" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
        return checked ? checkbox.replace('cbx', 'cbx layui-form-checked') : checkbox;
    }
    tree.prototype.renderTableHeader = function (e) {
        var dom = '', thead = '', n = j(e.elem).next();
        if (e.is_checkbox) {
            thead += '<th style="width:28px;">' + this.renderCkBox(j.inArray(e.top_value, e.checked.data) > -1) + '</th>';
        }
        if (e.render.thead && n.find('table thead').eq(0).remove()) {
            j.each(e.cols, function (index, item) {
                var style = '';
                item.width && (style += 'width:' + item.width + ';');
                item.align && (style += 'text-align:' + item.align + ';');
                style && (style = 'style="' + style + '"');
                thead += '<th ' + style + '>' + item.title + '</th>';
            });
            thead && (thead = '<tr data-id="' + e.top_value + '">' + thead + '</tr>');
            dom = '<thead>' + thead + '</thead>'
            n.children('table').eq(0).prepend(dom);
        }
    };
    tree.prototype.renderTable = function (e) {
        var t = this, dom = '', tbody = '', n = j(e.elem).next();
        if (e.render.tbody && n.find('table tbody').eq(0).remove()) {
            if (!e.data || e.data.length === 0) {
                var len = e.is_checkbox ? e.cols.length + 1 : e.cols.length;
                tbody = '<tr><td style="padding:15px 10px;text-align:center;color:#999" colspan="' + len + '">' + (e.error ? e.error : "无数据") + '</td></tr>';
            } else {
                j.each(t.fmt_data(e), function (idx, obj) {
                    var tr = '',
                        hide_class = (obj[e.parent_key] == e.top_value) || (obj[e.parent_key] == t.cache(e, obj[e.parent_key])) ? '' : e.hide_class;

                    if (e.is_checkbox) {
                        tr += '<td style="width:28px;">' + t.renderCkBox(j.inArray(obj[e.checked.key], e.checked.data) > -1) + '</td>';
                    }
                    j.each(e.cols, function (index, item) {
                        var style = '';
                        item.width && (style += 'width:' + item.width + ';');
                        item.align && (style += 'text-align:' + item.align + ';');
                        style && (style = 'style="' + style + '"');

                        // 指定列加入开启、关闭小图标
                        var icon = (item.key == e.icon_key && !obj.is_end) ? '<i class="' + (t.cache(e, obj[e.primary_key]) ? e.icon.open : e.icon.close) + '"></i>' : '<span></span>';
                        // 指定列小图标按照层级向后位移
                        var left = (item.key == e.icon_key ? obj.level * e.icon.left + 'px' : '');
                        icon = icon.replace('>', ' style="margin-left:' + left + ';">');
                        if (item.template && item.template.constructor === Function) {
                            tr += '<td ' + style + (left ? 'data-down' : '') + '>' + icon + item.template(obj) + '</td>';
                        } else if (item.tool && item.tool.constructor === String && item.tool.slice(0, 1) === '#') {
                            tr += '<td ' + style + (left ? 'data-down' : '') + '>' + icon + j("#actionBar").html() + '</td>';
                        } else {
                            tr += '<td ' + style + (left ? 'data-down' : '') + '>' + icon + obj[item.key] + '</td>';
                        }
                    });
                    tbody += '<tr class="' + hide_class + '" data-index="' + idx + '" data-id="' + obj[e.primary_key] + '" data-pid="' + obj[e.parent_key] + '">' + tr + '</tr>';
                })
            }
            dom = '<tbody>' + tbody + '</tbody>'
            n.children('table').eq(0).append(dom);
        }
    };
    tree.prototype.template = function (e) {
        var t = this, el = j(e.elem),
            dom = '<div class="layui-border-box table-view" lay-table-id="' + el.attr("id") + '"><table class="layui-table layui-form"></table></div>';
        if (el.next().attr('lay-table-id') !== e.elem.slice(1)) {
            el.after(dom);
        }
        t.renderTableTool(e);
        t.renderTableHeader(e);
        t.renderTable(e);

        var layBody = el.next();
        layBody.off('click', '[data-down]').on('click', '[data-down]', function () {
            var tr = j(this).parents('[data-id]'), td = tr.find('[data-down]'), id = tr.data('id'),
                is_open = (td.find('i:not(.layui-icon-ok)').attr('class') == e.icon.close);
            if (is_open) {
                // 展开子级（子级出现、更改图标）
                td.find('i:not(.layui-icon-ok)').attr('class', e.icon.open);
                td.parents('[lay-table-id=' + el.attr("id") + ']').find('[data-pid=' + id + ']').removeClass(e.hide_class);
                t.cache(e, id, true);
            } else {
                // 关闭子级（更改图标、隐藏所有子孙级）
                td.find('i:not(.layui-icon-ok)').attr('class', e.icon.close);
                t.children_hide(e, id);
            }
        }).off('click', 'td [lay-event]').on('click', 'td [lay-event]', function () {
            var data = e.data, index = j(this).parents('tr').eq(0).data('index'),
                tr = layBody.find('tr[data-index="' + index + '"]'), tabId = el.attr("id"), config = e;
            config.id = tabId;
            layui.event.call(this, MOD_NAME, "tool(" + tabId + ")", {
                elem: tr,
                event: j(this).attr('lay-event'),
                data: delete data[index]['level'] && delete data[index]['is_end'] && data[index],
                config: config,
                del: function () {
                    tr.remove();
                }
            })
        }).off('click', '.layui-table-tool [lay-event]').on('click', '.layui-table-tool [lay-event]', function () {
            var tabId = el.attr("id"), config = e;
            config.id = tabId;
            layui.event.call(this, MOD_NAME, "toolbar(" + tabId + ")", {
                elem: this,
                event: j(this).attr('lay-event'),
                config: config,
            })
        }).off('click', '.cbx').on('click', '.cbx', function () {
            var is_checked = j(this).toggleClass('layui-form-checked').hasClass('layui-form-checked'),
                tr = j(this).parents('[data-id]'),
                id = tr.data('id'),
                pid = tr.data('pid');
            t.children_checkbox(e, id, is_checked);
            t.parents_checkbox(e, pid);
            // 设置监听checkbox选择
            layui.event.call(this, MOD_NAME, 'tree(box)', {
                item: e.data[tr.data('index')] === undefined ? {} : e.data[tr.data('index')],
                table: e.elem,
                is_checked: is_checked,
            })
        });
        e.end && e.end(e);

        e.render.toolbar = false;
        e.render.thead = false;
        e.render.tbody = false;
    }
    // 同级全部选中父级选中/同级全部取消取消父级
    tree.prototype.parents_checkbox = function (e, parentId) {
        var el = j(e.elem).next(), po = el.find('[data-pid=' + parentId + ']'),
            co = el.find('[data-id=' + parentId + ']'),
            len = el.find('[data-pid=' + parentId + '] .cbx.layui-form-checked').length;
        if (po.length == len || len == 0) {
            var pid = co.data('pid');
            len ? co.find('.cbx').addClass('layui-form-checked') : co.find('.cbx').removeClass('layui-form-checked');
            pid === undefined || this.parents_checkbox(e, pid);
        }
    };
    // 子级反选
    tree.prototype.children_checkbox = function (e, id, is_checked) {
        var t = this;
        j(e.elem).next().find('[data-pid=' + id + ']').each(function () {
            var checkbox = j(this).find('.cbx');
            is_checked ? checkbox.addClass('layui-form-checked') : checkbox.removeClass('layui-form-checked');
            t.children_checkbox(e, j(this).data('id'), is_checked);
        })
    };
    tree.prototype.children_hide = function (e, id) {
        var t = this;
        t.cache(e, id, false);
        j(e.elem).next().find('[data-pid=' + id + ']:not(.' + e.hide_class + ')').each(function () {
            var td = j(this).find('[data-down]'),
                i = td.find('i:not(.layui-icon-ok)');
            // 关闭更换小图标
            i.length && i.attr('class', e.icon.close);
            // 隐藏子级
            j(this).parents('[lay-table-id=' + j(e.elem).attr("id") + ']').find('[data-pid=' + id + ']').addClass(e.hide_class);
            t.children_hide(e, j(this).data('id'))
        });
    };
    // 重新组合数据，父子级关系跟随
    tree.prototype.fmt_data = function (e) {
        var t = this, data = [], arr_id = [], arr_pid = [], children;
        e.data.forEach((item, index, arr) => {
            arr_id.push(item[e.primary_key]);
            arr_pid.push(item[e.parent_key]);
            arr[index]['is_end'] = false;
        })
        children = arr_id.filter(x => !arr_pid.includes(x));
        j.each(e.data, function (index, obj) {
            if (obj[e.parent_key] === e.top_value) {
                obj.level = 0;
                if (j.inArray(obj.id, children) > -1) {
                    obj.is_end = true;
                }
                data.push(obj);
                data.concat(t.tree_data(e, obj, data, children));
            }
        })
        e.data = data;
        return data;
    };
    tree.prototype.tree_data = function (e, obj, data, children) {
        var t = this;
        j.each(e.data, function (index, item) {
            if (item[e.parent_key] === obj[e.primary_key]) {
                item.level = obj.level + 1;
                if (j.inArray(item.id, children) > -1) {
                    item.is_end = true;
                }
                data.push(item);
                data.concat(t.tree_data(e, item, data, children));
            }
        })
        return data;

    }
    tree.prototype.openAll = function (e) {
        var t = this;
        j.each(e.data, function (idx, item) {
            item[e.primary_key] && t.cache(e, item[e.primary_key], true);
        })
        t.reload(e)
    }
    tree.prototype.closeAll = function (e) {
        localStorage.setItem(e.elem.substring(1), '');
        this.reload(e);
    }
    tree.prototype.getChecked = function (e) {
        var ids = [];
        j(e.elem).next().find('.cbx.layui-form-checked').each(function () {
            var id = j(this).parents('[data-id]').data('id');
            ids.push(id);
        })
        return ids.filter(item => item !== 0);
    }
    tree.prototype.reload = function (e, options) {
        var t = this, obj = {},
            args = ['where', 'headers', 'parseData', 'cols', 'data', 'url', 'top_value', 'primary_key', 'parent_key', 'icon', 'is_checkbox', 'checked', 'code', 'toolbar'];
        if (options instanceof Object) {
            j.each(options, function (key, value) {
                (j.inArray(key, args) > -1) && (obj[key] = value);
            })
            if (options.toolbar !== undefined && e.toolbar !== options.toolbar) {
                e.render.toolbar = true;
            }
            if ((options.is_checkbox !== undefined && e.is_checkbox !== options.is_checkbox) || (options.checked !== undefined && e.checked !== options.checked) || (options.cols !== undefined && e.cols !== options.cols)) {
                e.render.thead = true;
            }
            e = j.extend(e, obj);
        }
        if (typeof (options) === 'boolean' && options) {
            e.render = {toolbar: true, thead: true, tbody: true}
        }
        if (e.render !== undefined && e.render.constructor === Object) {
            e.render.tbody = true;
        } else {
            e.render = {toolbar: true, thead: true, tbody: true}
        }

        t.render(e);
    }
    tree.prototype.on = function (events, callback) {
        return layui.onevent.call(this, MOD_NAME, events, callback)
    };
    tree.prototype.render = function (e) {
        var t = this;
        e = j.extend(t.config(), e);
        if (e.url) {
            if (e.headers instanceof Object) {
                j.ajaxSetup({
                    headers: e.headers
                })
            }
            j.get(e.url, e.where, function (res) {
                if (e.parseData !== undefined && j.isFunction(e.parseData)) {
                    res = e.parseData(res);
                }
                if (res.code !== e.code) {
                    e.error = '响应格式：{ code: 0, msg: "", data: [] }';
                    e.data = [];
                } else {
                    e.error = false;
                    e.data = res.data;
                }
                t.template(e);
            })
        } else {
            t.template(e);
        }
        return e;
    };
    j("head").append('<style>.table-view .layui-table{margin: 0;}.table-view .layui-table-tool{border:1px solid #eee;border-bottom: 0;}.table-view thead tr{background-color: #FAFAFA;}</style>');

    exports(MOD_NAME, new tree())
});
